<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>021比较运算符和数据转换总结</title>
</head>

<body>
  <h1>021比较运算符和数据转换总结</h1>
  <script>
    /*
      1 比较运算符
        >
        >=
        <
        <=
        == 值相等即为true
        !=
        === 值和类型都相等即为true
        !==

      2 比较运算符返回的结果只能是true或者false
    */
    console.log(3 > 5) // false
    console.log(3 >= 3) // true
    console.log(2 == 2) // true
    console.log(2 == '2') // true
    console.log(2 != '2') // false
    console.log(2 === '2') // false
    console.log(2 !== '2') // true
    console.log(NaN == NaN) // false
    console.log(NaN === NaN) // false
    console.log('a' < 'b') // true
    console.log('aa' < 'ab') // true
    console.log('aa' < 'aac') // true
    console.log('---------------------------比较运算符----------------------------------')

    /*
      1 toString(其它类型转换成字符串)
        number类型，boolean类型，null，undefined直接包裹引号即可
        引用数据类型需要先toPrimitive，根据获取的原始值在进行转换

      2 toNumber(其它类型转换成数字)
        string类型 纯数字的字符串直接转为数字，含有其它字符的字符串需要视情况而定
        Boolean类型 true为1，false为0
        null为0
        undefined为NaN
        引用数据类型需要先toPrimitive，根据获取的原始值在进行转换

      3 toBoolean(其它类型转换成布尔值)
        number类型 0，NaN为false，其余均为true
        string类型 ''空串为false，其余均为true
        null为false
        undefined为false
        引用数据类型均为true

      4 toPrimitive
        大多数情况下：引用数据类型，先检查valueOf()的返回值，如果是原始值，则将原始值继续转换；
        如果没有valueOf()方法或者返回值不是原始值，继续检查toString()的返回值；
        如果valueOf()和toString()都没有返回值，则会抛出异常。
        特例：Date对象直接调用toString()方法。还有其它类似于Date对象的存在。
    */

    // toString
    console.log(String({})) // {}的valueOf()返回值是{}，则找toString()，其返回值是'[object Object]'
    console.log(String([])) // []的valueOf()返回值是[]，则找toString()，其返回值是空串''
    console.log(String([1, undefined, null, 4])) // null和undefined会被当做空串处理
    console.log('------------------------------toString-------------------------------')

    // toNumber
    console.log(Number({})) // {}的valueOf()返回值是{}，则找toString()，其返回值是'[object Object]'，继续转则为NaN
    console.log(Number([])) // []的valueOf()返回值是[]，则找toString()，其返回值是空串''，继续转则为0
    console.log(Number([1])) // []的valueOf()返回值是[1]，则找toString()，其返回值是空串'1'，继续转则为1
    console.log('-------------------------------toNumber------------------------------')

    // toPrimitive抛出异常
    let obj = {
      toString() {
        return {}
      }
    }
    // console.log(String(obj))
    // console.log(Number(obj))
    console.log('-------------------------------toPrimitive抛出异常------------------------------')

    /*
      5 ==宽等
        只要有一侧是boolean类型，就将boolean类型转换为number类型。
        一侧是number类型，一侧是string类型，就将string类型转换为number类型。
        一侧是引用数据类型，一侧是基本数据类型，就将引用数据类型根据toPrimitive规则获取原始值。
    */

    // 面试题 将a赋何值，这个等式成立：a == 1 && a == 2 && a == 3
    let a = {
      i: 1,
      toString() {
        return this.i++
      }
    }
    console.log(a == 1 && a == 2 && a == 3)
  </script>
</body>

</html>